---
title: "Undo / Redo Edits"
---

This section covers how to allow users to undo / redo their cell edits.

When [Cell Editing](./cell-editing/) is enabled in the grid, it is usually desirable to allow users to undo / redo any edits.

Users can change the contents of cells through the following grid features:

* [Cell Editing](./cell-editing/)
* [Copy / Paste](./clipboard/)
* [Fill Handle](./range-selection-fill-handle/)

{% note %}
This Undo / Redo feature is designed to be a recovery mechanism for user editing mistakes. Performing data updates (except for cell edits), or grid
operations that change the row / column order, e.g. sorting, filtering and grouping, will clear the
undo / redo stacks.
{% /note %}

## Enabling Undo / Redo

The following undo / redo properties are provided in the grid options interface:

```js {% frameworkTransform=true %}
const gridOptions = {
    undoRedoCellEditing: true,
    undoRedoCellEditingLimit: 20
}
```

As shown in the snippet above, undo / redo is enabled through the `undoRedoCellEditing` property.

The default number of undo / redo steps is `10`. To change this default the `undoRedoCellEditingLimit` property can be used.

## Undo / Redo Shortcuts

The following keyboard shortcuts are available when undo / redo is enabled:

* {% kbd "^ Ctrl" /%}+{% kbd "Z" /%} / {% kbd "Command" /%}+{% kbd "Z" /%}: will undo the last cell edit(s).
* {% kbd "^ Ctrl" /%}+{% kbd "Y" /%} / {% kbd "Command" /%}+{% kbd "Y" /%}: will redo the last undo.

Note that the grid needs focus for these shortcuts to have an effect.

## Undo / Redo API

It is also possible to programmatically control undo / redo and check the number of currently available undo / redo actions. These API methods are listed below:

{% apiDocumentation source="grid-api/api.json" section="UndoRedo" /%}

## Undo / Redo Events

The following events are relevant to undo / redo:

{% apiDocumentation source="grid-events/events.json" section="editing" names=["undoStarted", "undoEnded", "redoStarted", "redoEnded", "cellValueChanged"] /%}

For an undo / redo, the events will be fired as:

1. One `undoStarted` / `redoStarted` event.
1. Zero to many `cellValueChanged` events.
1. One `undoEnded` / `redoEnded` event.

When there are no undo / redo operations to perform, the started and ended events will still fire. However, the ended event will have a value of `false` for the `operationPerformed` property (compared to `true` when an operation was performed).

If the application is doing work each time it receives a `cellValueChanged` event, you can use the `undoStarted` / `redoStarted` and `undoEnded` / `redoEnded` events to suspend the application's work and then do the work for all cells impacted by the undo / redo operation afterwards.

If [Read Only Edit](./value-setters/#read-only-edit) is enabled, undo / redo will not perform any operations. The started and ended events will still fire, which means that you can implement your own undo / redo by keeping track of the `cellEditRequest` events.

## Example: Undo / Redo

The example below has the following grid options enabled to demonstrate undo / redo:

```js {% frameworkTransform=true spaceBetweenProperties=true %}
const gridOptions = {
    defaultColDef: {
        // makes all cells editable
        editable: true
    },
    // allows copy / paste using cell ranges
    enableRangeSelection: true,

    // enables the fill handle
    enableFillHandle: true,

    // enables undo / redo
    undoRedoCellEditing: true,

    // restricts the number of undo / redo steps to 5
    undoRedoCellEditingLimit: 5,

    // enables flashing to help see cell changes
    enableCellChangeFlash: true,
}
```

To see undo / redo in action, try the following:

* **Cell Editing**: click and edit some cell values.
* **Fill Handle**: drag the fill handle to change a range of cells.
* **Copy / Paste**: use {% kbd "^ Ctrl" /%}+{% kbd "C" /%} / {% kbd "^ Ctrl" /%}+{% kbd "V" /%} to copy and paste a range of cells.
* **Undo Shortcut**: use {% kbd "^ Ctrl" /%}+{% kbd "Z" /%} to undo the cell edits.
* **Redo Shortcut**: use {% kbd "^ Ctrl" /%}+{% kbd "Y" /%} to redo the undone cell edits.
* **Undo API**: use the 'Undo' button to invoke `gridApi.undoCellEditing()`.
* **Redo API**: use the 'Redo' button to invoke `gridApi.redoCellEditing()`.
* **Undo / Redo Limit**: only 5 actions are allowed as `undoRedoCellEditingLimit=5`.

{% gridExampleRunner title="Undo / Redo" name="undo-redo"  exampleHeight=530 /%}

## Complex Objects

If your cell values contain complex objects, there are a few steps necessary for undo / redo to work.

For manual editing, a [Value Parser](./value-parsers/) is required to convert string values back into complex objects.

```js {% frameworkTransform=true %}
const gridOptions = {
    columnDefs: [
        {
            field: 'a',
            editable: true,
            valueParser: params => {
                // convert `params.newValue` string value into complex object
                return {
                    actualValue: params.newValue,
                    anotherProperty: params.data.anotherProperty,
                }
            }
        }
    ]
}
```

If a [Value Getter](./value-getters/) is being used to create complex objects, a [Value Setter](./value-setters/) must be used to update the data. `colDef.equals` is also needed when [Comparing Values](./change-detection/#comparing-values) to determine if the cell value has changed for rendering.

```js {% frameworkTransform=true %}
const gridOptions = {
    columnDefs: [
        {
            field: 'a',
            editable: true,
            valueGetter: params => {
                // create complex object from data
                return {
                    actualValue: params.data[params.colDef.field],
                    anotherProperty: params.data.anotherProperty,
                }
            },
            valueSetter: params => {
                // update data from complex object
                params.data[params.colDef.field] = params.newValue.actualValue
                return true
            },
            equals: (valueA, valueB) => {
                // compare complex objects
                return valueA.actualValue === valueB.actualValue
            }
        }
    ]
}
```

Complex object cell values must be immutable. If the cell values are mutated, undo / redo will not be able to restore the original values. This means that the Value Parser must return a new complex object.

Using the [Cell Data Type](./cell-data-types/) `object` presets many of the grid features to allow complex objects to work without further configuration by leveraging the [Value Formatter](./value-formatters/) and Value Parser.

The following example demonstrates how to use complex objects with undo / redo.

* For column **A**:
  * A Value Getter is used to create complex objects from the data.
  * A Value Formatter is used to convert the complex objects into strings for rendering.
  * A Value Setter is used to update the data from the complex objects (the inverse of the Value Getter).
  * A Value Parser is used to convert the string values produced from cell editing into complex objects (the inverse of the Value Formatter).
  * A Column Definition `equals` function is provided to compare the complex objects (without this the grid would use reference equality, but this won't work here as the Value Getter returns a new object each time).
* For column **B**:
  * The column values are complex objects.
  * A Value Formatter is used to convert the complex objects into strings for rendering.
  * A Value Parser is used to convert the string values produced from cell editing into complex objects (the inverse of the Value Formatter).
* For all columns:
  * The cell data type is set to `object` to allow other grid features to work, such as the fill handle, copy, paste, etc.
* Try the following actions:
  * **Cell Editing**: click and edit some cell values.
  * **Fill Handle**: drag the fill handle to change a range of cells.
  * **Copy / Paste**: use {% kbd "^ Ctrl" /%}+{% kbd "C" /%} / {% kbd "^ Ctrl" /%}+{% kbd "V" /%} to copy and paste a range of cells.
  * **Undo Shortcut**: use {% kbd "^ Ctrl" /%}+{% kbd "Z" /%} to undo the cell edits.
  * **Redo Shortcut**: use {% kbd "^ Ctrl" /%}+{% kbd "Y" /%} to redo the undone cell edits.
  * **Undo API**: use the 'Undo' button to invoke `gridApi.undoCellEditing()`.
  * **Redo API**: use the 'Redo' button to invoke `gridApi.redoCellEditing()`.
  * **Undo / Redo Limit**: only 5 actions are allowed as `undoRedoCellEditingLimit=5`.

{% gridExampleRunner title="Undo / Redo with Complex Objects" name="undo-redo-complex-objects"  exampleHeight=530 /%}
